#include "serializer/serializer.h"

#include <gtest/gtest.h>

#include <array>
#include <deque>
#include <list>
#include <string>
#include <vector>

using namespace serializer;

/**
 * 往返序列化通用工具函数
 * 参数:
 * - value 输入值
 * - options 序列化选项
 * 返回值: 反序列化结果
 */
template <typename T>
T
roundtrip_via_cpo(const T & value, const default_options & options)
{
    vector_writer writer;
    serialize(writer, value, options);
    vector_reader reader(writer.data());
    return deserialize_cpo(reader, options, type_tag<T>);
}

TEST(cpo_containers_test, vector_and_list_and_deque_roundtrip)
{
    default_options options{};

    std::vector<int> vec{1, 2, 3, 4, 5};
    std::list<double> lst{1.5, 2.5, 3.5};
    std::deque<std::string> dq{"a", "b", "c"};

    auto vec_out = roundtrip_via_cpo(vec, options);
    auto lst_out = roundtrip_via_cpo(lst, options);
    auto dq_out = roundtrip_via_cpo(dq, options);

    EXPECT_EQ(vec_out, vec);
    EXPECT_EQ(std::vector<double>(lst_out.begin(), lst_out.end()),
              std::vector<double>(lst.begin(), lst.end()));
    EXPECT_EQ(std::vector<std::string>(dq_out.begin(), dq_out.end()),
              std::vector<std::string>(dq.begin(), dq.end()));
}

TEST(cpo_containers_test, array_roundtrip)
{
    default_options options{};

    std::array<int, 5> arr{10, 20, 30, 40, 50};
    auto arr_out = roundtrip_via_cpo(arr, options);
    EXPECT_EQ(arr_out, arr);
}

TEST(cpo_containers_test, nested_vector_roundtrip)
{
    default_options options{};

    std::vector<std::vector<int>> nested{{1, 2}, {3, 4, 5}, {6}};
    auto nested_out = roundtrip_via_cpo(nested, options);
    EXPECT_EQ(nested_out, nested);
}